﻿using System.Text;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Documents;
using System.Xml;
using System.IO;

namespace XAMLStylePad.Views
{
    public class XAMLEditor: RichTextBox
    {

        //public void LoadResourceDictionary(string packURI)
        //{
        //    Xamlloa
        //}

        public void SetXAML(object element)
        {
            if(element == null)
            {
                Document = new FlowDocument();
                return;
            }

            var settings = new XmlWriterSettings()
            {
                Indent = true,
                OmitXmlDeclaration = true
            };

            StringBuilder xaml = new StringBuilder();

            var manager = new XamlDesignerSerializationManager(XmlWriter.Create(xaml, settings))
            {
                XamlWriterMode = XamlWriterMode.Expression
            };

            XamlWriter.Save(element, manager);
            SetXAML(xaml.ToString());
            //using(var stream = new MemoryStream())
            //{
            //    SetXAML(stream);
            //}
        }

        void SetXAML(string xaml)
        {
            XmlDocument doc = new XmlDocument();
            
            doc.LoadXml(xaml);

            FlowDocument flow = new FlowDocument(new Paragraph(Format(null, doc.FirstChild, "")[0]));
            Document = flow;
        }

        private Inline[] Format(XmlNode parent, XmlNode node, string offset)
        {
            if(node is XmlElement)
            {
                if(parent!=null && node.Name.Contains("."))
                {  // parsing expanded properties

                    XamlAttribute attr = null;
                    string propName = node.Name.Substring(node.Name.IndexOf(".")+1);
                    var child = node.FirstChild;

                    if("Value Content".Contains(propName)) 
                    {  // If 'Value' or 'Content' property value is string, then show it as attributes
                        if(child.Name.StartsWith("s:"))
                        {
                            attr = new XamlAttribute(propName, child.FirstChild.Value);
                            return new Inline[]{attr};
                        }
                    }
                    else if( "BasedOn" == propName || ("Resources" == propName && child.ChildNodes.Count == 0))
                    {
                        return null;
                    }
                    else if(parent.ChildNodes.Count == 1 && "Children".Contains(propName))
                    {  // Hide <Children> tag, if only one child is present
                        node = node.FirstChild;
                    }
                }

                XamlTag tag = new XamlTag(node.Name, offset);

                foreach(XmlAttribute attr in node.Attributes)
                {
                    tag.AddAttribute(new XamlAttribute(attr));
                }

                foreach(XmlNode child in node.ChildNodes)
                {
                    if(!child.Name.StartsWith("#"))
                        tag.AddContent(Format(node, child, offset + XamlTag.Offset));
                    else if(child is XmlText)
                    {
                        tag.AddText(child.Value);
                    }
                }

                tag.EndTag();

                return new Inline[]{ tag};
            }
            return null;
        }
    }
}
